﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Room
{
    class Commands:ConsoleHandle
    {
        public const int cc = 9; // кол-во команд
        public const int pc = 9; // кол-во параметров

        static public string[,] coms = new string[cc, pc]
        {
            //[command name] [param0] [param1] [param2] [param3] [param4] [param5] [command info] [Handle INT] 
            {"help","<command name>","(none)","(none)","(none)","(none)","(none)","- Справочная система.","0"},
            {"server","start/stop","<host name>","<port>","(none)","(none)","(none)","- Работа с сервером.","1"},
            {"лень","(none)","(none)","(none)","(none)","(none)","(none)","- Автостарт сервера.","2"},
            {"sess","a/d/c/s","(none)","(none)","(none)","(none)","(none)","- Таблица сессий. Параметры: a - добавить, d - удалить, c - очистить.","3"},
            {"net","g","(none)","(none)","(none)","(none)","(none)","- Работа в сети Интернет. Параметры: g - сбор данных о машине.","4"},
            {"ping","<host>","(none)","(none)","(none)","(none)","(none)","- Отправка пакетов на указанный хост.","5"},
            {"exit","(none)","(none)","(none)","(none)","(none)","(none)","- Закрывает комнату и выходит из программы. Рекомендуется как безопасный выход из программы.","6"},
            {"ban","ip/name","a/d/s","<value>","(none)","(none)","(none)","- Работа с блок листами. Параметры: ip - работа с блок листом ip-адресов, name - работа с блок листом имен, a - добавить новое значение в блок лист, d - удалить значение из блок листа, s - выводит конкретное значение, <value> - используется в параметрах d и s.","7"},
            {"lvs","(none)","(none)","(none)","(none)","(none)","(none)","- Поиск ЛВСок.","8"}
        };

        static public void isCom(string com)
        {

            if (com.Length == 0)
            {
                write(0, "Введите команду для работы с сервером. Для справки введите \"help\".");
            }
            else
                if (com[0] == ' ')
                {
                    write(1, "Команда не должна начинаться с пробела.");
                }
                else
                {
                    string[] ub = com.Replace("\r\n", " ").Split(' ');
                    int ind = -1;
                    for (int i = 0; i < cc; ++i) if (coms[i, 0] == ub[0]) ind = i;
                    if (ind != -1)
                    {
                        try
                        {
                            switch (Convert.ToInt32(coms[ind, 8]))
                            {
                                case 0: HandleHelpCommand(ub); break;
                                case 1: HandleServerCommand(ub); break;
                                case 2: HandleLenCommand(ub); break;
                                case 3: HandleSessCommand(ub); break;
                                case 4: HandleNetCommand(ub); break;
                                case 5: HandlePingCommand(ub); break;
                                case 6: HandleExitCommand(ub); break;
                                case 7: HandleBanCommand(ub); break;
                                case 8: HandleLvsCommand(ub); break;

                                default: HandleDefaultCommand(); break;
                            }
                        }
                        catch (FormatException)
                        {
                            write(1, "При конвертации из coms[,] в Handle INT (блок Switch) возникла ошибка.");   
                        }
                    }
                    else write(1, "Команда \""+ub[0]+"\" не объявлена в процессоре команд.");
                }
        }

        /* ************Commands Handler************ */
        static public void HandleLvsCommand(string[] com)
        {
            write(0, "\nПоиск ЛВС...");
            int ad = 0;
            StringBuilder sb = new StringBuilder();
            foreach (System.Net.IPAddress ip in System.Net.Dns.GetHostByName(System.Net.Dns.GetHostName()).AddressList)
            {
                sb.AppendLine(ip.ToString());
                Console.WriteLine("Найден: " + ip.ToString());
                ad++;
            }
            Console.WriteLine("Всего: " + ad.ToString());
        }

        static public void HandleBanCommand(string[] com)
        {
            if (com.Length == 1) write(1, "У этой команды есть параметры. Введите \"help ban\" для вызова справки.");
            else
            {
                int ind = -1;
                if (com[1] == "ip") ind = 0;
                else
                    if (com[1] == "name") ind = 1; else write(1, "Указан не существующий блок лист.");

                if (com.Length == 2)
                {
                    if(ind!=-1) BlockLists.bWriteTable(ind);
                }
                else
                {
                    if (com[2] == "a")
                    {
                        string[] buf = new string[4];
                        int etap = 0;
                        string b = "";
                        while (etap != 4)
                        {
                            if (etap == 0)
                            {
                                if (ind == 0)
                                {
                                    write(2, "IP-adress:");
                                    b = Console.ReadLine();
                                    if (Core.isHost(b))
                                    {
                                        buf[0] = b;
                                        ++etap;
                                    }
                                }
                                else
                                    if (ind == 1)
                                    {
                                        write(2, "NickName:");
                                        b = Console.ReadLine();
                                        if (b.Length != 0)
                                        {
                                            buf[0] = b;
                                            ++etap;
                                        }
                                    }
                            }
                            if (etap == 1)
                            {
                                write(2, "Baned by:");
                                b = Console.ReadLine();
                                if ((b.Length != 0) && (b != buf[0]))
                                {
                                    buf[1] = b;
                                    ++etap;
                                }
                            }
                            if (etap == 2)
                            {
                                write(2, "Ban time(in hour):");
                                b = Console.ReadLine();
                                if (Core.isInt(b))
                                {
                                    buf[2] = b;
                                    ++etap;
                                }
                            }
                            if (etap == 3)
                            {
                                write(2, "Reason:");
                                b = Console.ReadLine();
                                if (b.Length != 0)
                                {
                                    buf[3] = b;
                                    ++etap;
                                }
                            }
                        }
                        BlockLists.bAddBan(ind, buf[0], buf[1], buf[2], buf[3]);
                    }
                    else
                        if (com[2] == "d")
                        {
                            if (com.Length == 3) write(1, "Не указан параметр <value>.");
                            else
                            {
                                BlockLists.bUnBan(ind, com[3]);
                            }
                        }
                        else
                            if (com[2] == "s")
                            {
                                if (com.Length == 3) write(1, "Не указан параметр <value>.");
                                else
                                {
                                    switch (ind)
                                    {
                                        case 0:
                                            {
                                                int ni = BlockLists.bBaned(0, com[3]);
                                                if (ni != -1)
                                                {
                                                    write(0, "\n[ip-adress] [banby] [baned] [unbaned] [reason]");
                                                    for (int i = 0; i < BlockLists.ccbl; ++i)
                                                        Console.Write("[" + BlockLists.blockIPs[ni, i] + "] ");
                                                    Console.WriteLine();
                                                }
                                                else write(1, "Значение \""+com[3]+"\" не найдено в блок листе (ip).");
                                            } break;
                                        case 1:
                                            {
                                                int ni = BlockLists.bBaned(1, com[3]);
                                                if (ni != -1)
                                                {
                                                    write(0, "\n[NickName] [banby] [baned] [unbaned] [reason]");
                                                    for (int i = 0; i < BlockLists.ccbl; ++i)
                                                        Console.Write("[" + BlockLists.blockNames[ni, i] + "] ");
                                                    Console.WriteLine();
                                                }
                                                else write(1, "Значение \"" + com[3] + "\" не найдено в блок листе (Names).");
                                            } break;
                                    }
                                }
                            }
                            else write(1, "Введена не верная команда для работы с блок листом.");
                }
            }
        }

        static public void HandleExitCommand(string[] com)
        {
            bool v = false;
            string c = "";
            while (true)
            {
                write(2, "Завершить работу программы?(y,n)");
                c = Console.ReadLine();
                if (c == "y")
                {
                    v = true;
                    break;
                }
                else
                    if (c == "n") break;
            }
            if (v)
            {
                write(0, "Спасибо, что выбрали безопасный выход из программы!");
                if (Core.started)
                {
                    string[] args = new string[3] { "server", "stop", "NQ" };
                    HandleServerCommand(args);
                }
                Head.echo = false;
            }
            else
                write(0, "Команда отменена.");
        }

        static public void HandlePingCommand(string[] com)
        {
            if (com.Length == 2)
            {
                string c = com[1];
                if ((c != "") && (c[0] != ' '))
                {
                    Core.ping(com[1]);
                }
                else write(1, "[HandlePingCommand] Для этой команды введен не верный параметр.");
            }
            else write(1, "[HandlePingCommand] У этой команды может быть только один параметр.");

        }
        static public void HandleNetCommand(string[] com)
        {
            if (com.Length == 1)
            {
                Core.Internet();
            }
            else
            {
                if (com[1] == "g")
                {
                    string[] dat = Core.getDataFromNet();
                    if (dat[0] == "(none)")
                    {
                        write(1, "Данные не получены. Возможно нет подключения к Интернету.");
                    }
                    else
                    {
                        write(3, "Машина:\n" +
                                " Адрес: " + dat[0] + "\n" +
                                " Прокси: " + dat[1] + "\n" +
                                " Провайдер: " + dat[2] + "\n" +
                                " Страна: " + dat[3]);
                    }
                }
                else write(1, "[HandleNetCommand] Не верный параметр для этой команды."); 
            }
        }
        static public void HandleSessCommand(string[] com)
        {
            if (com.Length == 1) Sessions.sWriteTable();
            else
                if (com.Length == 2)
                {
                    if (com[1] == "a")
                    {
                        int vvod = 0;
                        string v1 = "", v2 = "", v3 = "", v4 = "";
                        while (vvod != 4)
                        {
                            if (vvod == 0)
                            {
                                write(2, "SESSION:");
                                v1 = Console.ReadLine();
                                if (v1.Length == 16) vvod = 1;
                            }
                            if (vvod == 1)
                            {
                                write(2, "IP-Adress:");
                                v2 = Console.ReadLine();
                                if (Core.isHost(v2)) vvod = 2;
                            }
                            if (vvod == 2)
                            {
                                write(2, "HostName:");
                                v3 = Console.ReadLine();
                                if (v3.Length != 0) vvod = 3;
                            }
                            if (vvod == 3)
                            {
                                write(2, "ClientVersion:");
                                v4 = Console.ReadLine();
                                if (v4.Length != 0) vvod = 4;
                            }
                        }
                        Sessions.sAddSes(v1, v2, v3, v4);
                    }
                    else
                        if (com[1] == "d")
                        {
                            bool vvod = true;
                            string buf = "";
                            while (vvod)
                            {
                                write(2, "SESSION:");
                                buf = Console.ReadLine();
                                if (buf.Length != 0) vvod = false;
                            }
                            Sessions.sDelSes(buf);
                        }
                        else
                            if (com[1] == "c")
                            {
                                Sessions.sSetNullTable();
                            }
                            else write(1, "[HandleSessCommand] Не верный параметр для этой команды.");
                }
                else write(1, "[HandleSessCommand] У этой команды может быть только один параметр. Для справки введите \"help sess\".");
        }

        static public void HandleHelpCommand(string[] com)
        {
            if (com.Length == 1)
            {
                write(0, "Список доступных команд (Их всего "+cc.ToString()+"):");
                Console.ForegroundColor = ConsoleColor.Cyan;
                for (int i = 0; i < cc; ++i)
                {
                    for (int j = 0; j < pc - 1; ++j)
                    {
                        if (coms[i, j] != "(none)")
                        {
                            if (j == 0) Console.Write(" [" + coms[i, j] + "]" + " ");
                            else
                                Console.Write(coms[i, j] + " ");
                        }
                    }
                    Console.Write("\n");
                }
            }
            else
            {
                int ind = -1;
                for (int i = 0; i < cc; ++i) if (coms[i, 0] == com[1]) ind = i;
                if (ind == -1) write(1, "[HandleHelpCommand] Команда '" + com[1] + "' не существует.");
                else
                {
                    string[] st = new string[pc];
                    for (int i = 0; i < pc; ++i) st[i] = coms[ind, i];
                    Console.ForegroundColor = ConsoleColor.Cyan;
                    for (int i = 0; i < pc - 1; ++i) if (st[i] != "(none)") Console.Write(st[i] + " ");
                    Console.Write("\n");
                }
            }
        }

        static public void HandleServerCommand(string[] com)
        {
            if (com.Length == 1)
            {
                write(1, "Команда имеет параметры. Для справки введите \"help server\"."); 
            }else
            if ((com[1] != "start") && (com[1]!="stop"))
            {
                write(1, "Введен не верный параметр. Для справки введите \"help server\".");
            }else
                if (com[1] == "start")
                {
                    if (Core.started)
                    {
                        write(1, "Сервер уже запущен.");
                    }else
                    if (com.Length == 2)
                    {
                        write(1, "Задан параметр start, но не указан параметр <host name>.");
                    }
                    else
                        if (!Core.isHost(com[2]))
                        {
                            write(1, "Параметр <host name> имеет не верный формат. Попробуйте снова.");
                        }
                        else if (com.Length == 3)
                        {
                            write(1, "Задан параметр start, но не указан дополнительный параметр <port>.");
                        }
                        else if (!Core.isPort(com[3]))
                        {
                            write(1, "Порт \""+com[3]+"\" запрещен.");
                        }
                        else
                        {
                            //и наконецто старт сервера :) Методы всякие
                            Sessions.sSetNullTable();
                            //**************************
                            write(4, "Сервер как бы запущен!");
                            Core.started = true;
                        }
                }
                else if (com[1] == "stop")
                {
                    if (!Core.started)
                    {
                        write(0, "Сервер не запущен.");
                    }
                    else
                    {
                        bool yesQ = true;
                        if (com.Length == 3)
                        {
                            if (com[2] == "NQ") yesQ = false;
                            //тут как бы завершение сервера (типа метода чтоли) из core...
                            write(4, "Сервер как бы отпущен.");
                            Core.started = false;
                            //************************************************************
                        }
                        if (yesQ)
                        {
                            string ans = "";
                            while ((ans != "y") || (ans != "n"))
                            {
                                write(2, "Остановить сервер?(y/n)");
                                ans = Console.ReadLine();
                                if (ans == "n")
                                {
                                    write(0, "Команда отменена.");
                                    break;
                                }
                                else
                                    if (ans == "y")
                                    {
                                        //тут как бы завершение сервера (типа метода чтоли) из core...
                                        write(4, "Сервер как бы отпущен.");
                                        Core.started = false;
                                        break;
                                        //************************************************************
                                    }
                            }
                        }
                    }
                }
        }

        static public void HandleLenCommand(string[] com)
        {
            if (Core.started)
            {
                write(3, "Понял! Закрываю комнату...");
                string[] args = new string[3] { "server", "stop", "NQ" };
                HandleServerCommand(args);
            }
            else
            {
                write(3, "Понял! Начинаю запуск сервера на своё усмотрение...");
                //*Если есть инет, то лучше туда сервер выдвенуть... хуже не будет :)
                write(3, "Проверка доступа к Интернету...");
                if (Core.Internet())
                {
                    string[] dat = Core.getDataFromNet();
                    write(3, "Данные:\n" +
                            " Дом компа: " + dat[0] + "\n" +
                            " Прокси: " + dat[1] + "\n" +
                            " Провайдер: " + dat[2] + "\n" +
                            " Страна: " + dat[3]);
                    string h = dat[0];
                    write(3, "Зафиксирован HostName: " + h);
                    string p = GetConfig("Net", "dPort");
                    write(3, "Порт по умолчанию: "+p+". Зафиксирован.");
                    write(3, "Передаю параметры для запуска сервера...");
                    string[] args = new string[4] { "server", "start", h, p };
                    HandleServerCommand(args);
                }
                else
                {
                    write(3,"Нету доступа к Интернету! :( Ладно, не киснем! Шарим по ЛВC. :)");
                    //если нет инета, тогда шарим по ЛВС ... 
                    write(3, "Поиск ЛВС...");
                    int ad = 0;
                    StringBuilder sb = new StringBuilder();
                    foreach (System.Net.IPAddress ip in System.Net.Dns.GetHostByName(System.Net.Dns.GetHostName()).AddressList)
                    {
                        sb.AppendLine(ip.ToString());
                        write(3, "Найден: " + ip.ToString());
                        ad++;
                    }
                    string st = sb.ToString();
                    string[] hs = st.Replace("\r\n", " ").Split(' ');

                    //Если мы одиноки, то ставим сервер только для нас... 
                    if ((hs[0] == "127.0.0.1") && (hs[1]==""))
                    {
                        write(3, "И ЛВСки у нас нет! :( Ну и тут не теряемся, ставим сервер на LocalHost! :)");
                        write(3, "[System.Net.IPAddress] Этот компьютер не подключен ни к одной сети.");
                        write(3, hs[0] + " - назначен как HostName для сервера.");
                        string p = GetConfig("Net", "dPort");
                        write(3, "Порт: "+p+". Зафиксирован.");
                        string[] args = new string[4] { "server", "start", hs[0],p};
                        HandleServerCommand(args);
                    }else
                        if (hs[1]=="")
                        {
                            write(3, "Ура! Мы не одни в этой вселенной! :) Ставим сервер на единственный хост из ЛВС.");
                            string h = hs[0];
                            write(3, "HostName: " + h + " - Зафиксирован!");
                            h = h.Replace("\n", " ");
                            h = h.Trim();
                            string p = GetConfig("Net", "dPort");
                            write(3, "Port: " + p + " - Зафиксирован!");
                            string[] args = new string[4] { "server", "start", h, p };
                            HandleServerCommand(args);
                        }
                }         
            }
        }

        static private void HandleDefaultCommand()
        {
            write(1, "[Handle] Switch case: default.");
        }
        /* **************************************** */
    }
}
